package com.hd.sup.modules.alarm.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hd.common.constant.BizConstant;
import com.hd.common.reqres.response.Result;
import com.hd.common.utils.CollectionUtils;
import com.hd.common.utils.GenUtil;
import com.hd.common.utils.Pair;
import com.hd.sup.config.redis.prefix.CacheKey;
import com.hd.sup.config.redis.utils.JedisUtil;
import com.hd.sup.modules.alarm.mapper.AlarmRuleVehicleMapper;
import com.hd.sup.modules.alarm.model.AlarmRule;
import com.hd.sup.modules.alarm.model.AlarmRuleVehicle;
import com.hd.sup.modules.alarm.service.IAlarmRuleService;
import com.hd.sup.modules.alarm.service.IAlarmRuleVehicleService;
import com.hd.sup.modules.vehicle.model.Vehicle;
import com.hd.sup.modules.vehicle.service.IVehicleService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author chentl123
 * @since 2021-01-07
 */
@Slf4j
@Service
public class AlarmRuleVehicleServiceImpl extends ServiceImpl<AlarmRuleVehicleMapper, AlarmRuleVehicle> implements IAlarmRuleVehicleService {

    public static final int SPLIT_SIZE = 10000;
    public static final int INIT_CURSOR = 0;

    @Resource
    private JedisUtil jedisUtil;

    @Resource
    private IAlarmRuleService alarmRuleService;

    @Override
    public List<Map<String, Object>> pageList(Page page, AlarmRuleVehicle param) {
        return this.baseMapper.pageList(page, param);
    }

    @Override
    public void deleteVehicleRules(String ruleId, String ruleTransType) {
        AlarmRule ruleDb = alarmRuleService.getById(ruleId);
        BizConstant.AlarmType alarmType = BizConstant.AlarmType.get(ruleDb.getAlarmType());
        if (Objects.isNull(alarmType)) return;

        List<String> transTypeList = Lists.newArrayList();
        if (ruleTransType.equals(BizConstant.RuleTransType.PASSENGER.key())) {
            transTypeList.add(BizConstant.VehicleTransType.PASSENGER.key());
            transTypeList.add(BizConstant.VehicleTransType.TRAVEL.key());
        } else if (ruleTransType.equals(BizConstant.RuleTransType.DANGER.key())) {
            transTypeList.add(BizConstant.VehicleTransType.DANGER.key());
        } else if (ruleTransType.equals(BizConstant.RuleTransType.FREIGHT.key())) {
            transTypeList.add(BizConstant.VehicleTransType.FREIGHT.key());
        }

        if (CollectionUtils.isEmpty(transTypeList)) return;

        transTypeList.forEach(trans_type -> {
            //删除指定规则所绑定的 运输类型
            remove(new LambdaQueryWrapper<AlarmRuleVehicle>().eq(AlarmRuleVehicle::getRuleId, ruleId).eq(AlarmRuleVehicle::getTransType, trans_type));

            //清理缓存
            jedisUtil.hdel(GenUtil.cacheKey(CacheKey.TRANSTYPE_RULE_KEY, alarmType.val()), trans_type);
        });


    }

    @Override
    public Pair<String, String> bindTransType(String ruleId, BizConstant.RuleTransType ruleTransType) {
        List<String> transTypeList = Lists.newArrayList();

        if (ruleTransType.equals(BizConstant.RuleTransType.ALL)) {
            transTypeList.add(BizConstant.VehicleTransType.PASSENGER.key());
            transTypeList.add(BizConstant.VehicleTransType.FREIGHT.key());
            transTypeList.add(BizConstant.VehicleTransType.DANGER.key());
            transTypeList.add(BizConstant.VehicleTransType.TRAVEL.key());
        } else if (ruleTransType.equals(BizConstant.RuleTransType.PASSENGER)) {
            transTypeList.add(BizConstant.VehicleTransType.PASSENGER.key());
            transTypeList.add(BizConstant.VehicleTransType.TRAVEL.key());
        } else if (ruleTransType.equals(BizConstant.RuleTransType.DANGER)) {
            transTypeList.add(BizConstant.VehicleTransType.DANGER.key());
        } else if (ruleTransType.equals(BizConstant.RuleTransType.FREIGHT)) {
            transTypeList.add(BizConstant.VehicleTransType.FREIGHT.key());
        }


        List<AlarmRuleVehicle> distributedTs = list(new LambdaQueryWrapper<AlarmRuleVehicle>().eq(AlarmRuleVehicle::getRuleId, ruleId));
        Map<String, String> distributedTsMap = Maps.newHashMap();
        Map<String, String> unDistributedTsMap = Maps.newHashMap();

        for (AlarmRuleVehicle arv : distributedTs) {
            distributedTsMap.put(arv.getTransType(), BizConstant.Common.POINT.key());
        }

        for (String transType : transTypeList) {
            unDistributedTsMap.put(transType, BizConstant.Common.POINT.key());
        }

        if (MapUtils.isEmpty(unDistributedTsMap)) return Pair.makePair("平台中没有可分配的运输类型", ruleId);

        List<AlarmRuleVehicle> arvs = Lists.newArrayList();
        unDistributedTsMap.forEach((k, v) -> {
            if (!distributedTsMap.containsKey(k)) {
                //已分配的key中不存在则 添加
                AlarmRuleVehicle arv = new AlarmRuleVehicle(ruleId, k);
                arvs.add(arv);
            }
        });

        //后入
        saveBatch(arvs);

        //异步 将 指定规则对应的 每个车辆运输类型的规则绑定关系刷入redis
        cacheVehicleRules(ruleId, transTypeList);

        return Pair.makePair("", ruleId);
    }

    @Override
    public void cacheVehicleRules(String ruleId, List<String> transTypes) {
        //构造待写入对象
        Map<String, List<Map<String, Object>>> all = Maps.newHashMap();

        if (CollectionUtils.isEmpty(transTypes)) return;

        AlarmRule ruleDb = alarmRuleService.getById(ruleId);
        BizConstant.AlarmType alarmType = BizConstant.AlarmType.get(ruleDb.getAlarmType());

        if (Objects.isNull(alarmType)) return;

        List<Map<String, Object>> cacheList = Lists.newArrayList();

        for (String transType : transTypes) {
            Map<String, Object> vMap = Maps.newHashMap();
            vMap.put(BizConstant.Common.FIELD.key(), transType);
            vMap.put(BizConstant.Common.VAL.key(), JSON.toJSON(ruleDb));
            cacheList.add(vMap);
        }

        all.put(GenUtil.cacheKey(CacheKey.TRANSTYPE_RULE_KEY, alarmType.val()), cacheList);

        //缓存
        jedisUtil.hsetbatch(all);
        log.info("[redis] 车辆规则配置已缓存");
    }


    /**
     * @return java.util.List<java.lang.String>
     * @author chentl
     * @description 递归查询所有集合, 每次10000条
     * @date 2021/1/27 3:27 下午
     * @params [vehicleIds, list]
     */
    public List<AlarmRule> getBindLists(int cursor, List<String> vehicleIds, List<AlarmRule> list) {
        int end = vehicleIds.size();
        int offset = cursor + SPLIT_SIZE;
        List<AlarmRule> currentList;
        if (end > offset) {
            currentList = alarmRuleService.getAlarmRuleList(vehicleIds.subList(cursor, offset));
            cursor += SPLIT_SIZE;
            list.addAll(currentList);
        } else {
            currentList = alarmRuleService.getAlarmRuleList(vehicleIds.subList(cursor, end));
            list.addAll(currentList);
            return list;
        }

        return getBindLists(cursor, vehicleIds, list);
    }

}
